/*-----------------------------------------------File Info------------------------------------------------
** File Name:               i2c_user.c  
** Last modified date:      2016.07.22
** Last version:            V0.1
** Description:             
**--------------------------------------------------------------------------------------------------------            
** Created date:            2016.09.07
** author:                  YLY
** Version:                 V0.1
** Descriptions:            I2c驱动 
**--------------------------------------------------------------------------------------------------------
*/

/*************************************************************
* 	include 
* 	头文件	
*************************************************************/ 
#include "bspDma.h"

#ifdef DMA_EN
static volatile tsDmaSta tgDmaSta={ .eCH0Sta=DMA_CLOSE,
									.eCH1Sta=DMA_CLOSE,
									.eCH2Sta=DMA_CLOSE,
									.eCH3Sta=DMA_CLOSE,
									.eCH4Sta=DMA_CLOSE };

									
void setDmaSta(dma_channel_enum channelx, teDmaRunSta eSta)
{
	switch(channelx)
	{
		case DMA_CH0:
		{
			tgDmaSta.eCH0Sta = eSta;
		}break;
		case DMA_CH1:
		{
			tgDmaSta.eCH1Sta = eSta;
		}break;
		case DMA_CH2:
		{
			tgDmaSta.eCH2Sta = eSta;
		}break;
		case DMA_CH3:
		{
			tgDmaSta.eCH3Sta = eSta;
		}break;
		case DMA_CH4:
		{
			tgDmaSta.eCH4Sta = eSta;
		}break;	
		
#if BSP_MCU_TYPE == BSP_MCU_GD32F3x0
		
		case DMA_CH5:
		{
			tgDmaSta.eCH5Sta = eSta;
		}break;	
		
		case DMA_CH6:
		{
			tgDmaSta.eCH6Sta = eSta;
		}break;			
#endif		
	}
}

teDmaRunSta eGetDmaSta(dma_channel_enum channelx)
{
	switch(channelx)
	{
		case DMA_CH0:
		{
			return tgDmaSta.eCH0Sta;
		}break;
		
		case DMA_CH1:
		{
			return tgDmaSta.eCH1Sta;
		}break;
		
		case DMA_CH2:
		{
			return tgDmaSta.eCH2Sta;
		}break;
		
		case DMA_CH3:
		{
			return tgDmaSta.eCH3Sta;
		}break;
		
		case DMA_CH4:
		{
			return tgDmaSta.eCH4Sta;
		}break;	
		
#if BSP_MCU_TYPE == BSP_MCU_GD32F3x0
		
		case DMA_CH5:
		{
			return tgDmaSta.eCH5Sta;
		}break;	
		
		case DMA_CH6:
		{
			return tgDmaSta.eCH6Sta;
		}break;			
#endif 		
	}
}

void setDmaCallBack(dma_channel_enum channelx, tpDmaCallBack ptCb)
{
	switch(channelx)
	{
		case DMA_CH0:
		{
			tgDmaSta.ptvCH0Cb = ptCb;
		}break;
		
		case DMA_CH1:
		{
			tgDmaSta.ptvCH1Cb = ptCb;
		}break;
		
		case DMA_CH2:
		{
			tgDmaSta.ptvCH2Cb = ptCb;
		}break;
		
		case DMA_CH3:
		{
			tgDmaSta.ptvCH3Cb = ptCb;
		}break;
		
		case DMA_CH4:
		{
			tgDmaSta.ptvCH4Cb = ptCb;
		}break;	
		
#if BSP_MCU_TYPE == BSP_MCU_GD32F3x0
		
		case DMA_CH5:
		{
			tgDmaSta.ptvCH5Cb = ptCb;
		}break;	
		
		case DMA_CH6:
		{
			tgDmaSta.ptvCH6Cb = ptCb;
		}break;			
#endif 			
	}
}

/*
	channelx:
		DMA_CH0 = 0,	DMA Channel0 
		DMA_CH1,		DMA Channel1  
		DMA_CH2,		DMA Channel2  
		DMA_CH3,		DMA Channel3 
		DMA_CH4,		DMA Channel4 
	pStr:
	eRW:
		DMA_READ,
		DMA_WRITE,
	
*/
bool dmaInit(dma_channel_enum channelx, teDmaRW eRW, 
			 uint8_t *pMemory, uint32_t periph_addr, uint32_t number, tpDmaCallBack ptCb)
{
	dma_parameter_struct tPara;	
	uint32_t i=0;

	//dma_struct_para_init(&tPara);
	
	rcu_periph_clock_enable(RCU_DMA);
		
	while(eGetDmaSta(channelx) == DMA_OPEN)//等待DMA关闭
	{
		bspDelayMs(1);
		if(++i > 500)
			return false;
	}	
	
	dma_deinit(channelx); 
	
	setDmaSta(channelx, DMA_OPEN);			//设置DMA状态
	
	setDmaCallBack(channelx, ptCb);	//设置回调

	if(eRW == DMA_WRITE)
		tPara.direction = DMA_MEMORY_TO_PERIPHERAL;		//内存到外设
	else
		tPara.direction =  DMA_PERIPHERAL_TO_MEMORY;	//外设到内存
	
	tPara.memory_addr = (uint32_t)pMemory;				//内存地址
	tPara.memory_inc = DMA_MEMORY_INCREASE_ENABLE;		//内存地址自增
	tPara.memory_width = DMA_MEMORY_WIDTH_8BIT;			//内存8位宽

	tPara.periph_addr = periph_addr;					//外设地址
	tPara.periph_inc = DMA_PERIPH_INCREASE_DISABLE;		//禁止外设地址自增
	tPara.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;		//外设8位

	tPara.number = number;								//传输数量	
	tPara.priority = DMA_PRIORITY_ULTRA_HIGH;			//优先级
		
	dma_init(channelx, &tPara);		//初始化DMA	
	
	switch(channelx)
	{
#if BSP_MCU_TYPE == BSP_MCU_GD32E23x		
		case DMA_CH0:
		{
			nvic_irq_enable(DMA_Channel0_IRQn, 0);
		}break;
	
		case DMA_CH1:
		case DMA_CH2:
		{
			nvic_irq_enable(DMA_Channel1_2_IRQn, 0);
		}break;

		case DMA_CH3:
		case DMA_CH4:
		{
			nvic_irq_enable(DMA_Channel3_4_IRQn, 0);
		}break;	
#elif BSP_MCU_TYPE == BSP_MCU_GD32F3x0
		case DMA_CH0:
		{
			nvic_irq_enable(DMA_Channel0_IRQn, 2, 2);
		}break;
	
		case DMA_CH1:
		case DMA_CH2:
		{
			nvic_irq_enable(DMA_Channel1_2_IRQn, 2, 2);
		}break;

		case DMA_CH3:
		case DMA_CH4:
		{
			nvic_irq_enable(DMA_Channel3_4_IRQn, 2, 2);
		}break;	
		
		case DMA_CH5:
		case DMA_CH6:
		{
			nvic_irq_enable(DMA_Channel5_6_IRQn, 2, 2);
		}break;				
#endif 			
	}	
	
	/* configure DMA mode */
	dma_circulation_disable(channelx);				//禁止循环模块
	dma_memory_to_memory_disable(channelx);			//禁止内存到内存
	
	/* enable DMA transfer complete interrupt */
	dma_interrupt_enable(channelx, DMA_INT_FTF);	//使能中断
	dma_interrupt_enable(channelx, DMA_INT_ERR);	//使能中断	
	
	/* enable DMA channel  */
	dma_channel_enable(channelx);					//始能DAM通道
	return true;
}

void damDinit(dma_channel_enum channelx)
{
	dma_channel_disable(channelx);
	dma_deinit(channelx);
	setDmaSta(channelx, DMA_CLOSE);	
}



/*!
    \brief      this function handles DMA_Channel0_IRQHandler interrupt
    \param[in]  none
    \param[out] none
    \retval     none
*/
void DMA_Channel0_IRQHandler(void)
{
	if(dma_interrupt_flag_get(DMA_CH0, DMA_INT_FLAG_FTF))	//传送完成
	{  
		if(tgDmaSta.ptvCH0Cb)
			tgDmaSta.ptvCH0Cb(DMA_SUCCESS);	
		damDinit(DMA_CH0);				
        dma_interrupt_flag_clear(DMA_CH0, DMA_INT_FLAG_G);
    }
	else if(dma_interrupt_flag_get(DMA_CH0, DMA_INT_FLAG_HTF))	//半传完成
	{  
		if(tgDmaSta.ptvCH0Cb)
			tgDmaSta.ptvCH0Cb(DMA_HALF_FINISH);	

        dma_interrupt_flag_clear(DMA_CH0, DMA_INT_FLAG_G);
    }	
    else if(dma_interrupt_flag_get(DMA_CH0, DMA_INT_FLAG_ERR))	//错误
	{     
		if(tgDmaSta.ptvCH0Cb)
			tgDmaSta.ptvCH0Cb(DMA_FAIL);
		
		damDinit(DMA_CH0);
        dma_interrupt_flag_clear(DMA_CH0, DMA_INT_FLAG_G);
    }	
}

/*!
    \brief      this function handles DMA_Channel1_2_IRQHandler interrupt
    \param[in]  none
    \param[out] none
    \retval     none
*/
void DMA_Channel1_2_IRQHandler(void)
{
	if(dma_interrupt_flag_get(DMA_CH1, DMA_INT_FLAG_FTF))	//传送完成
	{  
		if(tgDmaSta.ptvCH1Cb)
			tgDmaSta.ptvCH1Cb(DMA_SUCCESS);	
		damDinit(DMA_CH1);				
        dma_interrupt_flag_clear(DMA_CH1, DMA_INT_FLAG_G);
    }
	else if(dma_interrupt_flag_get(DMA_CH1, DMA_INT_FLAG_HTF))	//半传完成
	{  
		if(tgDmaSta.ptvCH1Cb)
			tgDmaSta.ptvCH1Cb(DMA_HALF_FINISH);	

        dma_interrupt_flag_clear(DMA_CH1, DMA_INT_FLAG_G);
    }	
    else if(dma_interrupt_flag_get(DMA_CH1, DMA_INT_FLAG_ERR))	//错误
	{     
		if(tgDmaSta.ptvCH1Cb)
			tgDmaSta.ptvCH1Cb(DMA_FAIL);
		
		damDinit(DMA_CH1);
        dma_interrupt_flag_clear(DMA_CH1, DMA_INT_FLAG_G);
    }	
	
	if(dma_interrupt_flag_get(DMA_CH2, DMA_INT_FLAG_FTF))	//传送完成
	{  
		if(tgDmaSta.ptvCH2Cb)
			tgDmaSta.ptvCH2Cb(DMA_SUCCESS);	
		damDinit(DMA_CH2);				
        dma_interrupt_flag_clear(DMA_CH2, DMA_INT_FLAG_G);
    }
	else if(dma_interrupt_flag_get(DMA_CH2, DMA_INT_FLAG_HTF))	//半传完成
	{  
		if(tgDmaSta.ptvCH2Cb)
			tgDmaSta.ptvCH2Cb(DMA_HALF_FINISH);	

        dma_interrupt_flag_clear(DMA_CH2, DMA_INT_FLAG_G);
    }	
    else if(dma_interrupt_flag_get(DMA_CH2, DMA_INT_FLAG_ERR))	//错误
	{     
		if(tgDmaSta.ptvCH2Cb)
			tgDmaSta.ptvCH2Cb(DMA_FAIL);
		
		damDinit(DMA_CH2);
        dma_interrupt_flag_clear(DMA_CH2, DMA_INT_FLAG_G);
    }	
}


/*!
    \brief      this function handles DMA_Channel3_4_IRQHandler interrupt
    \param[in]  none
    \param[out] none
    \retval     none
*/
void DMA_Channel3_4_IRQHandler(void)
{
	if(dma_interrupt_flag_get(DMA_CH3, DMA_INT_FLAG_FTF))	//传送完成
	{  
		if(tgDmaSta.ptvCH3Cb)
			tgDmaSta.ptvCH3Cb(DMA_SUCCESS);	
		damDinit(DMA_CH3);				
        dma_interrupt_flag_clear(DMA_CH3, DMA_INT_FLAG_G);
    }
	else if(dma_interrupt_flag_get(DMA_CH3, DMA_INT_FLAG_HTF))	//半传完成
	{  
		if(tgDmaSta.ptvCH3Cb)
			tgDmaSta.ptvCH3Cb(DMA_HALF_FINISH);	

        dma_interrupt_flag_clear(DMA_CH3, DMA_INT_FLAG_G);
    }	
    else if(dma_interrupt_flag_get(DMA_CH3, DMA_INT_FLAG_ERR))	//错误
	{     
		if(tgDmaSta.ptvCH3Cb)
			tgDmaSta.ptvCH3Cb(DMA_FAIL);
		
		damDinit(DMA_CH3);
        dma_interrupt_flag_clear(DMA_CH3, DMA_INT_FLAG_G);
    }	
	
	if(dma_interrupt_flag_get(DMA_CH4, DMA_INT_FLAG_FTF))	//传送完成
	{  
		if(tgDmaSta.ptvCH4Cb)
			tgDmaSta.ptvCH4Cb(DMA_SUCCESS);	
		damDinit(DMA_CH4);				
        dma_interrupt_flag_clear(DMA_CH4, DMA_INT_FLAG_G);
    }
	else if(dma_interrupt_flag_get(DMA_CH4, DMA_INT_FLAG_HTF))	//半传完成
	{  
		if(tgDmaSta.ptvCH4Cb)
			tgDmaSta.ptvCH4Cb(DMA_HALF_FINISH);	

        dma_interrupt_flag_clear(DMA_CH4, DMA_INT_FLAG_G);
    }	
    else if(dma_interrupt_flag_get(DMA_CH4, DMA_INT_FLAG_ERR))	//错误
	{     
		if(tgDmaSta.ptvCH4Cb)
			tgDmaSta.ptvCH4Cb(DMA_FAIL);
		
		damDinit(DMA_CH4);
        dma_interrupt_flag_clear(DMA_CH4, DMA_INT_FLAG_G);
    }		
}

#if BSP_MCU_TYPE == BSP_MCU_GD32F3x0
void DMA_Channel5_6_IRQHandler(void)
{
	if(dma_interrupt_flag_get(DMA_CH5, DMA_INT_FLAG_FTF))	//传送完成
	{  
		if(tgDmaSta.ptvCH5Cb)
			tgDmaSta.ptvCH5Cb(DMA_SUCCESS);	
		damDinit(DMA_CH5);				
        dma_interrupt_flag_clear(DMA_CH5, DMA_INT_FLAG_G);
    }
	else if(dma_interrupt_flag_get(DMA_CH5, DMA_INT_FLAG_HTF))	//半传完成
	{  
		if(tgDmaSta.ptvCH5Cb)
			tgDmaSta.ptvCH5Cb(DMA_HALF_FINISH);	

        dma_interrupt_flag_clear(DMA_CH5, DMA_INT_FLAG_G);
    }	
    else if(dma_interrupt_flag_get(DMA_CH5, DMA_INT_FLAG_ERR))	//错误
	{     
		if(tgDmaSta.ptvCH5Cb)
			tgDmaSta.ptvCH5Cb(DMA_FAIL);
		
		damDinit(DMA_CH5);
        dma_interrupt_flag_clear(DMA_CH5, DMA_INT_FLAG_G);
    }	
	
	if(dma_interrupt_flag_get(DMA_CH6, DMA_INT_FLAG_FTF))	//传送完成
	{  
		if(tgDmaSta.ptvCH6Cb)
			tgDmaSta.ptvCH6Cb(DMA_SUCCESS);	
		damDinit(DMA_CH6);				
        dma_interrupt_flag_clear(DMA_CH6, DMA_INT_FLAG_G);
    }
	else if(dma_interrupt_flag_get(DMA_CH6, DMA_INT_FLAG_HTF))	//半传完成
	{  
		if(tgDmaSta.ptvCH6Cb)
			tgDmaSta.ptvCH6Cb(DMA_HALF_FINISH);	

        dma_interrupt_flag_clear(DMA_CH6, DMA_INT_FLAG_G);
    }	
    else if(dma_interrupt_flag_get(DMA_CH6, DMA_INT_FLAG_ERR))	//错误
	{     
		if(tgDmaSta.ptvCH6Cb)
			tgDmaSta.ptvCH6Cb(DMA_FAIL);
		
		damDinit(DMA_CH6);
        dma_interrupt_flag_clear(DMA_CH6, DMA_INT_FLAG_G);
    }		
}			
#endif 		//BSP_MCU_GD32F3x0
#endif		//DMA_EN